package com.framework.auth.controller;

import com.framework.auth.param.ClientParam;
import com.framework.auth.service.IUserService;
import com.framework.auth.util.SecurityUtil;
import com.framework.common.model.CommonUser;
import com.framework.common.model.UserInfo;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.Map;
import java.util.UUID;

@Controller
@Api(tags = "api")
public class ApiController {
    @Resource
    private RegisteredClientRepository registeredClientRepository;

    @Autowired
    private IUserService userService;

    @Autowired
    private JwtDecoder jwtDecoder;

    @RequestMapping(value = "/user/info")
    @ResponseBody
    public UserInfo getUser(HttpServletRequest request) {
        String token = SecurityUtil.getToken(request);
        Jwt jwt = jwtDecoder.decode(token);
        Map<String, Object> map = jwt.getClaims();
        String name = (String) map.get("sub");
        UserInfo userInfo = userService.getUserInfoByUserName(name);
        if (ObjectUtils.isNotEmpty(userInfo)) {
            CommonUser commonUser = userInfo.getSysUser();
            if (ObjectUtils.isNotEmpty(commonUser)) {
                commonUser.setPassword(null);
            }
        }
        userInfo.getSysUser();
        return userInfo;
    }

    @GetMapping("/login")
    public String login() {
        return "login";
    }

    @GetMapping("/api/addClient")
    @ResponseBody
    public String addClient(@RequestBody ClientParam param) {
        // JWT（Json Web Token）的配置项：TTL、是否复用refreshToken等等
        TokenSettings tokenSettings = TokenSettings.builder()
                // 令牌存活时间：2小时
                .accessTokenTimeToLive(Duration.ofHours(24))
                // 令牌可以刷新，重新获取
                .reuseRefreshTokens(true)
                // 刷新时间：30天（30天内当令牌过期时，可以用刷新令牌重新申请新令牌，不需要再认证）
                .refreshTokenTimeToLive(Duration.ofDays(30))
                .build();
        // 客户端相关配置
        ClientSettings clientSettings = ClientSettings.builder()
                // 是否需要用户授权确认
                .requireAuthorizationConsent(false)
                .build();

        RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
                // 客户端ID和密码
                .clientId(param.getClientId())
//                .clientSecret("{bcrypt}" + new BCryptPasswordEncoder().encode("secret"))
                .clientSecret(new BCryptPasswordEncoder().encode(param.getClientSecret()))
                // 授权方法
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT)
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                // 授权模式（授权码模式）
                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                // 刷新令牌（授权码模式）
                .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
                .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
                // 回调地址：授权服务器向当前客户端响应时调用下面地址, 不在此列的地址将被拒绝, 只能使用IP或域名，不能使用 localhost
                .redirectUri(param.getRedirectUri())
                // OIDC 支持
                .scope(OidcScopes.OPENID)
                .scope(OidcScopes.PROFILE)
                // 授权范围（当前客户端的授权范围）
                .scope("read")
                .scope("write")
                // JWT（Json Web Token）配置项
                .tokenSettings(tokenSettings)
                // 客户端配置项
                .clientSettings(clientSettings)
                .build();

        registeredClientRepository.save(registeredClient);
        return "添加客户端信息成功";
    }

}
